import {
  BaseCommand,
  pickedFaceData,
  pickedLineData,
  Types,
} from '@amcax/base';
import { PickInputRJSFFormat } from '@app-base/common/components/command-form/constants';
import { PickableCommandForm } from '@app-base/common/components/command-form/pickable';
import { useCommand } from '@app-base/common/hooks/useCommand';
import { getIdOfPickedObj } from '@app-base/common/utils/render';
import { docMgr, previewer } from '@app-base/module';
import { wsApi } from '@app-base/server';
import { i18n } from '@app-nextmesh/common/utils';
import { RJSFSchema, UiSchema } from '@rjsf/utils';

import { useEffect, useState } from 'react';
import { Vector3 } from 'three-legacy';

interface SolidMixDialogProps {
  title: string;
  onClose: () => void;
}
type PickedData = pickedLineData | pickedFaceData;
type MixFormData = {
  profile1: PickedData;
  vector1: PickedData | null;
  profile2: PickedData;
  vector2: PickedData | null;
};
function SolidMixView({ title, onClose }: SolidMixDialogProps) {
  const [formData, setFormData] = useState<MixFormData>({
    profile1: null,
    vector1: null,
    profile2: null,
    vector2: null,
  });
  const [isProfileSketch, setIsProfileSketch] = useState(false);
  const [isProfileSecondSketch, setIsProfileSecondSketch] = useState(false);

  useEffect(() => {
    if (!isValid()) return;
    preview();
  }, [formData]);

  useEffect(() => {
    if (formData.profile1) {
      const isSketch =
        docMgr.getDocumentObjectById(formData.profile1?.idInfo.o)?.type ===
        Types.Sketcher;
      setIsProfileSketch(isSketch);
    }
    if (formData.profile2) {
      const isSketch2 =
        docMgr.getDocumentObjectById(formData.profile2?.idInfo.o)?.type ===
        Types.Sketcher;
      setIsProfileSecondSketch(isSketch2);
    }
  }, [formData.profile1, formData.profile2]);
  const schema: RJSFSchema = {
    type: 'object',
    properties: {
      profile1: {
        type: 'string',
        title: '第一轮廓',
        format: PickInputRJSFFormat.PickCurveAndPlane,
      },
      vector1: {
        type: 'string',
        title: '第一方向',
        format: PickInputRJSFFormat.PickDirection,
      },
      profile2: {
        type: 'string',
        title: '第二轮廓',
        format: PickInputRJSFFormat.PickCurveAndPlane,
        uniqueItems: true,
      },
      vector2: {
        type: 'string',
        title: '第二方向',
        format: PickInputRJSFFormat.PickDirection,
      },
    },
  };
  const uiSchema: UiSchema = {
    profile1: {
      'ui:placeholder': '第一轮廓',
      'ui:autofocus': true,
    },
    vector1: {
      'ui:placeholder': isProfileSketch ? '第一方向(默认法向量)' : '第一方向',
    },
    profile2: {
      'ui:placeholder': '第二轮廓',
    },
    vector2: {
      'ui:placeholder': isProfileSecondSketch
        ? '第二方向(默认法向量)'
        : '第二方向',
    },
  };
  // 根据不同平面，找出对应的向量
  const getObjectNormal = (obj) => {
    let normal = new Vector3();
    if (obj.meshId === 'XOZ') {
      normal = new Vector3(0, 0, 1);
    } else if (obj.meshId === 'XOY') {
      normal = new Vector3(0, 1, 0);
    } else if (obj.meshId === 'YOZ') {
      normal = new Vector3(1, 0, 0);
    } else {
      const faceIndex = obj.meshId.split(':')[1]?.substring(1);
      const normalVec = obj.modelData?.faces[faceIndex ?? 0].normals?.[0];
      normal = new Vector3(normalVec[0], normalVec[1], normalVec[2]);
    }
    return normal;
  };
  const prepareParams = () => {
    const { profile1, profile2, vector1, vector2 } = formData;
    const profile1_id = getIdOfPickedObj(profile1);
    const profile2_id = getIdOfPickedObj(profile2);
    const params = {
      profile1: profile1_id,
      profile2: profile2_id,
    };

    const getVectorFromArray = (pickedData) => {
      if (pickedData.meshId) {
        return getObjectNormal(pickedData).toArray();
      } else if (pickedData.edgeId) {
        const edgeNormal = pickedData.edgeData[1]
          .clone()
          .sub(pickedData.edgeData[0]);
        return edgeNormal.toArray();
      }
      return null;
    };

    const vectors = [vector1, vector2];
    const vectorKeys = ['vector1', 'vector2'];

    vectors.forEach((vector, index) => {
      if (vector) {
        const vectorArray = getVectorFromArray(vector);
        if (vectorArray) {
          params[vectorKeys[index]] = vectorArray;
        }
      }
    });

    return params;
  };
  const handleSubmit = async () => {
    const params = prepareParams();
    await wsApi.createEntityMix(params);
    cancelAction();
  };

  const isValid = () => {
    const { profile1, profile2, vector1, vector2 } = formData;
    // 情况1: 当两个轮廓都有值，并且两个方向向量都有值时
    if (profile1 && profile2 && vector1 && vector2) {
      return true;
    }
    // 情况2: 当两个轮廓都是草图轮廓时
    if (isProfileSketch && isProfileSecondSketch) {
      return true;
    }
    // 情况3: 当至少有一个轮廓是草图轮廓，并且至少有一个方向向量有值时
    if ((isProfileSketch || isProfileSecondSketch) && (vector1 || vector2)) {
      return true;
    }
    return false;
  };

  const cancelAction = () => {
    previewer.clear();
    onClose();
  };
  const { previewInCommand } = useCommand('cmd-solid-mix', {
    onClose: cancelAction,
  });
  const preview = async () => {
    const params = prepareParams();
    const result = await wsApi.createEntityMix(params, true);
    previewInCommand(result);
  };
  return (
    <PickableCommandForm
      schema={schema}
      title={title}
      onClose={onClose}
      extraUiSchema={uiSchema}
      onSubmit={handleSubmit}
      formData={formData}
      isFormDataValid={isValid()}
      onChange={(v) => {
        setFormData(v);
      }}
    />
  );
}

export const cmdSolidMix: BaseCommand = {
  id: 'cmdSolidMix',
  label: 'command.solid-mix',
  icon: 'commands/feature/solid-combine',
  create: (label, onClose) => (
    <SolidMixView
      title={i18n.t(label)}
      onClose={onClose}
    />
  ),
};
